package api.betfairAPI;

import com.betfair.www.publicapi.types.exchange.v5.*;
import com.betfair.www.publicapi.types.global.v3.*;
import com.betfair.www.publicapi.v3.bfglobalservice.BFGlobalServiceStub;
import com.betfair.www.publicapi.v5.bfexchangeservice.BFExchangeServiceStub;
import org.apache.axis2.AxisFault;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.log4j.Logger;

/**
 * User: Darren
 * Date: 5/01/13
 * Time: 9:57 AM
 */
class BetfairAPIStub {
    private static Logger logger = Logger.getLogger(BetfairAPIStub.class);
    private String sessionToken = null;
    private com.betfair.www.publicapi.types.global.v3.APIRequestHeader globalHeader =
            new com.betfair.www.publicapi.types.global.v3.APIRequestHeader();
    private com.betfair.www.publicapi.types.exchange.v5.APIRequestHeader exchHeader =
            new com.betfair.www.publicapi.types.exchange.v5.APIRequestHeader();

    private BFGlobalServiceStub globalServiceStub;
    private BFExchangeServiceStub ausExchStub;
    private BFExchangeServiceStub ukExchStub;

    BetfairAPIStub() throws AxisFault {
        initGlobalServiceStub();
        initAUSExchServiceStub();
        initUKExchServiceStub();
    }

    private void initGlobalServiceStub() throws AxisFault {
        try {
            globalServiceStub = new BFGlobalServiceStub();
        } catch (AxisFault e) {
            logger.fatal(e.toString());
            e.printStackTrace();
            throw e;
        }
        // http://axis.apache.org/axis2/java/core/api/org/apache/axis2/client/Stub.html
        // http://axis.apache.org/axis2/java/core/api/org/apache/axis2/client/Options.html
        // 20 seconds for a response from the API
        globalServiceStub._getServiceClient().getOptions().setTimeOutInMilliSeconds(20 * 1000);
        // http://axis.apache.org/axis2/java/core/api/org/apache/axis2/transport/http/HTTPConstants.html
        globalServiceStub._getServiceClient().getOptions().setProperty(HTTPConstants.MC_ACCEPT_GZIP, "true");
        globalServiceStub._getServiceClient().getOptions().setProperty(HTTPConstants.MC_GZIP_RESPONSE, "true");
    }
    private void initAUSExchServiceStub() throws AxisFault {
        try {
            ausExchStub = new BFExchangeServiceStub("https://api-au.betfair.com/exchange/v5/BFExchangeService");
        } catch (AxisFault e) {
            logger.fatal(e.toString());
            e.printStackTrace();
            throw e;
        }
        ausExchStub._getServiceClient().getOptions().setTimeOutInMilliSeconds(20 * 1000);
        ausExchStub._getServiceClient().getOptions().setProperty(HTTPConstants.MC_ACCEPT_GZIP, "true");
        ausExchStub._getServiceClient().getOptions().setProperty(HTTPConstants.MC_GZIP_RESPONSE, "true");
    }
    private void initUKExchServiceStub() throws AxisFault {
        try {
            ukExchStub = new BFExchangeServiceStub("https://api.betfair.com/exchange/v5/BFExchangeService");
        } catch (AxisFault e) {
            logger.fatal(e.toString());
            e.printStackTrace();
            throw e;
        }
        ukExchStub._getServiceClient().getOptions().setTimeOutInMilliSeconds(20 * 1000);
        ukExchStub._getServiceClient().getOptions().setProperty(HTTPConstants.MC_ACCEPT_GZIP, "true");
        ukExchStub._getServiceClient().getOptions().setProperty(HTTPConstants.MC_GZIP_RESPONSE, "true");
    }

    public BFGlobalServiceStub getGlobalServiceStub() {
        return globalServiceStub;
    }
    public BFExchangeServiceStub getExchangeServiceStub(int exchangeId) {
        if (exchangeId == BetfairExchangeMarket.UK_EXCHANGE_ID)
            return ukExchStub;
        else {
            return ausExchStub;
        }
    }

    public boolean responseValid(LoginResp resp) {
        if (resp.getErrorCode() == LoginErrorEnum.OK || resp.getErrorCode() == LoginErrorEnum.OK_MESSAGES) {
            if (resp.getErrorCode() == LoginErrorEnum.OK_MESSAGES) {
                logger.info("There are additional messages on your account, log into the Betfair website to view.");
            }
            setSessionToken(resp.getHeader());
            return true;
        } else if (resp.getErrorCode() == LoginErrorEnum.API_ERROR) {
            responseHeaderValid(resp.getHeader());
            return false;
        } else {
            logger.error("Betfair loginResp error: " + resp.getErrorCode().getValue());
            return false;
        }
    }
    public boolean responseValid(LogoutResp resp) {
        if (resp.getErrorCode() == LogoutErrorEnum.OK) {
            setSessionToken(resp.getHeader());
            return true;
        } else {
            responseHeaderValid(resp.getHeader());
            return false;
        }
    }
    public boolean responseValid(GetEventTypesResp resp) {
        if (resp.getErrorCode() == GetEventsErrorEnum.OK) {
            setSessionToken(resp.getHeader());
            return true;
        } else if (resp.getErrorCode() == GetEventsErrorEnum.API_ERROR) {
            responseHeaderValid(resp.getHeader());
            return false;
        } else {
            logger.error("Betfair GetEventTypesResp error: " + resp.getErrorCode().getValue());
            return false;
        }
    }
    public boolean responseValid(GetEventsResp resp) {
        if (resp.getErrorCode() == GetEventsErrorEnum.OK) {
            setSessionToken(resp.getHeader());
            return true;
        } else if (resp.getErrorCode() == GetEventsErrorEnum.API_ERROR) {
            responseHeaderValid(resp.getHeader());
            return false;
        } else {
            logger.error("Betfair GetEventResp error: " + resp.getErrorCode().getValue());
            return false;
        }
    }
    public boolean responseValid(GetMarketResp resp) {
        if (resp.getErrorCode() == GetMarketErrorEnum.OK) {
            setSessionToken(resp.getHeader());
            return true;
        } else if (resp.getErrorCode() == GetMarketErrorEnum.API_ERROR) {
            responseHeaderValid(resp.getHeader());
            return false;
        } else {
            logger.error("Betfair GetMarketResp error: " + resp.getErrorCode().getValue());
            return false;
        }
    }
    public boolean responseValid(GetMarketPricesCompressedResp resp) {
        if (resp.getErrorCode() == GetMarketPricesErrorEnum.OK) {
            setSessionToken(resp.getHeader());
            return true;
        } else if (resp.getErrorCode() == GetMarketPricesErrorEnum.API_ERROR) {
            responseHeaderValid(resp.getHeader());
            return false;
        } else {
            logger.error("Betfair GetMarketPricesCompressedResp error: " + resp.getErrorCode().getValue());
            return false;
        }
    }

    private boolean responseHeaderValid(com.betfair.www.publicapi.types.global.v3.APIResponseHeader header) {
        if (header.getErrorCode() != com.betfair.www.publicapi.types.global.v3.APIErrorEnum.OK) {
            logger.error("Betfair response header error: " + header.getErrorCode().getValue());
            return false;
        }
        return true;
    }
    private boolean responseHeaderValid(com.betfair.www.publicapi.types.exchange.v5.APIResponseHeader header) {
        if (header.getErrorCode() != com.betfair.www.publicapi.types.exchange.v5.APIErrorEnum.OK) {
            logger.error("Betfair response header error: " + header.getErrorCode().getValue());
            return false;
        }
        return true;
    }

    private void setSessionToken(com.betfair.www.publicapi.types.global.v3.APIResponseHeader header) {
        sessionToken = header.getSessionToken();
    }
    private void setSessionToken(com.betfair.www.publicapi.types.exchange.v5.APIResponseHeader header) {
        sessionToken = header.getSessionToken();
    }

    public void initGlobalRequest(com.betfair.www.publicapi.types.global.v3.APIRequest req) {
         globalHeader.setSessionToken(sessionToken);
         req.setHeader(globalHeader);
    }
    public void initExchRequest(com.betfair.www.publicapi.types.exchange.v5.APIRequest req) {
        exchHeader.setSessionToken(sessionToken);
        req.setHeader(exchHeader);
    }
}
